home *** CD-ROM | disk | FTP | other *** search
/ Freaks Macintosh Archive / Freaks Macintosh Archive.bin / Freaks Macintosh Archives / Ham⁄GPS / SoftKiss.src.1.8 Folder / SoftKiss.src.1.8 / core / sfk_core_kiss.c < prev    next >
Text File  |  1993-07-08  |  9KB  |  378 lines

  1. /*
  2.  * SoftKiss - kiss mode emulator
  3.  * by Aaron Wohl / N3LIW (aw0g+@andrew.cmu.edu) jul 1992
  4.  * 6393 Penn Ave #303
  5.  * Pittsburgh PA, 15206
  6.  * work: (412)-268-5032
  7.  * home: (412)-731-6159
  8.  */
  9.  
  10. #include "sfk_core.h"
  11. #include "sfk_core_private.h"
  12. #include "driver_shell.h"
  13. #include <Serial.h>
  14. #include <ctype.h>
  15.  
  16. #define FEND     0xc0        //end/start of frame
  17. #define FESC     0xdb        //transpose next character
  18. #define TFEND    0xdc        //transposed end
  19. #define TFESC    0xdd        //transposed escape
  20.  
  21. #define TRANSPOSE_PROTECT 0x100
  22.  
  23. //input port states
  24. #define KWP_LEAD_SYNC     0 //send out leading sync
  25. #define KWP_PORT        1 //send port number/cmd
  26. #define KWP_DATA        2 //send data byte
  27. #define KWP_TFEND        3 //send transposed end
  28. #define KWP_TFESC        4 //send transposed esc
  29.  
  30. /*
  31.  * refill current packet being read
  32.  */
  33. static sfk_packet_pt kiss_refill_pak(sfk_prt_pt p)
  34. {
  35.     sfk_packet_pt pak=p->K_IN.kp;
  36.     if(pak!=0)
  37.         return pak;
  38.     pak=sfk_dequeue_protected(&p->sfk_recvq);
  39.     if(pak==0)
  40.         return 0;        //no data available
  41.     p->K_IN.kp=pak;
  42.     p->K_IN.kp_offset=0;
  43.     return pak;
  44. }
  45.  
  46. /*
  47.  * read some data from packets into the serial input buffer
  48.  */
  49. static int kiss_read(sfk_prt_pt p,int is_async)
  50. {
  51.     register IOParam *ipb= p->K_IN.kp_pb;
  52.     sfk_packet_pt pak=kiss_refill_pak(p);
  53.     unsigned char ch;
  54.     if(pak==0)
  55.         return 1;
  56.     if(ipb==0)
  57.         return 1;    //no serial buffer to read into
  58.     while(TRUE) {
  59.         if(ipb->ioActCount>=ipb->ioReqCount)
  60.             goto done;    //output buffer changed
  61.         switch(p->K_IN.kp_state) {
  62.         case KWP_LEAD_SYNC:
  63.             *(ipb->ioBuffer+ipb->ioActCount++)=FEND;
  64.             p->K_IN.kp_state=KWP_PORT;
  65.             break;
  66.         case KWP_PORT:    //send recieved port number
  67.             *(ipb->ioBuffer+ipb->ioActCount++)=0;
  68.             p->K_IN.kp_state=KWP_DATA;
  69.             break;
  70.         case KWP_DATA:
  71.             //end of packet?
  72.             if(p->K_IN.kp_offset>=pak->cnt) { //yes
  73.                 *(ipb->ioBuffer+ipb->ioActCount++)=FEND;
  74.                 p->K_IN.kp_state=KWP_LEAD_SYNC;
  75.                 p->K_IN.kp=0;
  76.                 p->K_IN.kp_offset=0;
  77.                 sfk_free_packet_protected(p,pak);
  78.                 if((pak=kiss_refill_pak(p))==0)
  79.                     goto done;    //no more data to send
  80.                 continue;        //more data so start next
  81.             }
  82.             ch= *(pak->data+p->K_IN.kp_offset++);
  83.             if(ch==FEND) {
  84.                 p->K_IN.kp_state=KWP_TFEND;
  85.                 ch=FESC;
  86.             } else if(ch==FESC) {
  87.                 p->K_IN.kp_state=KWP_TFESC;
  88.                 ch=FESC;
  89.             }
  90.             *(ipb->ioBuffer+ipb->ioActCount++)=ch;
  91.             break;
  92.         case KWP_TFEND:
  93.             *(ipb->ioBuffer+ipb->ioActCount++)=TFEND;
  94.             p->K_IN.kp_state=KWP_DATA;
  95.             break;
  96.         case KWP_TFESC:
  97.             *(ipb->ioBuffer+ipb->ioActCount++)=TFESC;
  98.             p->K_IN.kp_state=KWP_DATA;
  99.             break;
  100.         }
  101.     }
  102. /*
  103.  * done for one of two reasons, no more data to send
  104.  * or no more room to put it.  In eithor case
  105.  * let the pending read request finish
  106.  * since something was read
  107.  */
  108. done:
  109.     if(is_async)
  110.         sfk_mark_read_done(p,0);    //read all we need to
  111.     else {
  112.         p->K_IN.kp_pb->ioResult=0;
  113.         p->K_IN.kp_pb=0;
  114.     }
  115.     return 0;
  116. }
  117.  
  118. #define KCMD_TXDELAY    1
  119. #define KCMD_P            2
  120. #define KCMD_SlotTime    3
  121. #define KCMD_TXtail        4
  122. #define KCMD_FullDuplex    5
  123. #define KCMD_SetHardware 6
  124. #define KCMD_Return        0x0FF
  125.  
  126. /*
  127.  * recieve a kiss command
  128.  */
  129. static void kiss_cmd(sfk_prt_pt p,unsigned long cmd_arg)
  130. {
  131.     switch(p->K_OUT.kp_cmd) {
  132.     case KCMD_TXDELAY:
  133.         p->sfk_IVAR(tx_delay)=(cmd_arg*10L)*1000L;
  134.         sfk_recompute_derived_nums(p);
  135.         break;
  136.     case KCMD_P:
  137.         p->sfk_IVAR(xmit_persist)= (cmd_arg*1000L)/255L;
  138.         break;
  139.     case KCMD_SlotTime:
  140.         p->sfk_IVAR(xmit_slottime)=(cmd_arg*10L)*1000L;
  141.         sfk_recompute_derived_nums(p);
  142.         break;
  143.     case KCMD_TXtail:
  144.         p->sfk_IVAR(tail_delay)=(cmd_arg*10L)*1000L;
  145.         sfk_recompute_derived_nums(p);
  146.         break;
  147.     case KCMD_FullDuplex:
  148.         break;
  149.     case KCMD_SetHardware:
  150.         break;
  151.     case KCMD_Return:
  152.         sfk_go_offline(p);
  153.         break;
  154.     }
  155. }
  156.  
  157. /*
  158.  * write some output characters
  159.  */
  160. static void kiss_write_out(sfk_prt_pt p,long cnt,unsigned char *buf)
  161. {
  162.   unsigned int ch;
  163.   while(cnt-- >0) {
  164.       ch= *buf++;
  165.       if(p->K_OUT.kp_transpose) {
  166.           p->K_OUT.kp_transpose=FALSE;
  167.         switch(ch) {
  168.          case TFEND:
  169.              ch=FEND|TRANSPOSE_PROTECT;
  170.              break;
  171.          case TFESC:
  172.              ch=FESC|TRANSPOSE_PROTECT;
  173.              break;
  174.          default:
  175.              p->K_OUT.kp_state=KRP_NP;    /*hunt for sync character*/
  176.          }
  177.      } else if(ch==FESC) {
  178.          p->K_OUT.kp_transpose=TRUE;
  179.          continue;
  180.      }
  181.     switch(p->K_OUT.kp_state) {
  182.        case KRP_NP:        //no packet hunt for sync
  183.            if(p->K_OUT.kp!=0) { //if have a packet buffer loose it
  184.                sfk_free_packet_protected(p,p->K_OUT.kp);
  185.             p->K_OUT.kp=0;
  186.         }
  187.         if(ch!=FEND)continue;
  188.            p->K_OUT.kp_state=KRP_SYNC;
  189.            break;
  190.        case KRP_READ_CMD:    //in sync wait for start of packet
  191.          p->K_OUT.kp_state=KRP_NP; //all commands 1 byte, wait for sync
  192.          kiss_cmd(p,ch);
  193.          break;
  194.        case KRP_SYNC:    //in sync wait for start of packet
  195.        {    int cmd= ch&0x0FF;
  196.            int pnum= (ch>>4)&0x0FF;
  197.         if(ch==FEND)continue;
  198.         /*first byte is command and port*/
  199.         if(cmd!=0) {
  200.             p->K_OUT.kp_state=KRP_READ_CMD;
  201.             p->K_OUT.kp_cmd=cmd;
  202.             continue;
  203.         }
  204.         if((pnum!=0)||(p->K_OUT.kp=sfk_allocate_protected(p))==0) {
  205.                 p->K_OUT.kp_state=KRP_NP;
  206.                  continue;
  207.          }
  208.            p->K_OUT.kp_state=KRP_WP;
  209.            p->K_OUT.kp->cnt=0;
  210.            p->K_OUT.kp->data_flags=0;
  211.            break;            //chuck first (command) byte
  212.        case KRP_WP:
  213.            if(ch!=FEND) {
  214.                *(p->K_OUT.kp->cnt+p->K_OUT.kp->data)=ch;
  215.                p->K_OUT.kp->cnt++;
  216.                if(p->K_OUT.kp->cnt>=p->sfk_IVAR(max_packet_size))
  217.                   p->K_OUT.kp_state=KRP_NP;
  218.              continue;
  219.            }
  220.            // end of input packet
  221.         p->K_OUT.kp_state=KRP_SYNC;
  222.            if(p->K_OUT.kp->cnt<SFK_MIN_PACK_SIZE)
  223.             sfk_free_packet_protected(p,p->K_OUT.kp);
  224.         else    //queue compleated packet for transmit
  225.             sfk_enqueue_write(p,p->K_OUT.kp);
  226.         p->K_OUT.kp=0;
  227.            break;
  228.         }
  229.       }
  230.     }
  231. }
  232.  
  233. /*
  234.  * fake driver for serial output in kiss mode
  235.  */
  236. static short kiss_out(CntrlParam *pb,DCtlPtr de,short op,void *extra)
  237. {
  238.     register IOParam *ipb= (IOParam *)pb;
  239.     sfk_prt_pt p=extra;
  240.     switch(op) {
  241.     case sh_OPEN:
  242.         if(sfk_open_me(de))
  243.             return ioErr;
  244.         break;
  245.     case sh_CLOSE:
  246.         sfk_close_me(de);
  247.         break;
  248.     case sh_PRIME:
  249.         if(p->sfk_IVAR(online))
  250.             kiss_write_out(p,ipb->ioReqCount,(unsigned char*)ipb->ioBuffer);
  251.         break;
  252.     default:
  253.         // DBO_fprintf((&p->dbo,"kiss_out csCode=%d\n",pb->csCode));
  254.         break;
  255.     }
  256.     return 0;
  257. }
  258.  
  259. /*
  260.  * return an estimate of the number of bytes to read
  261.  */
  262. static long kiss_bytes_available(sfk_prt_pt p)
  263. {
  264.     long result=0;
  265.     sfk_packet_pt pak;
  266.     if(!p->sfk_IVAR(online))    //if not online, no data to read
  267.         return 0;
  268.     pak=kiss_refill_pak(p);        //get current packet
  269.     if(pak==0)
  270.         return 0;            //no packet so no data
  271.     if(p->K_IN.kp_state==KWP_LEAD_SYNC)
  272.         result+=2;                //count sync and port
  273.     result+=(pak->cnt-p->K_IN.kp_offset)+1;
  274.     return result;                 //return amount of unread data
  275. }
  276.  
  277. /*
  278.  * init the variables in a kiss port
  279.  */
  280. static void kiss_clear_port(kiss_port_pt k)
  281. {
  282.     k->kp=0;
  283.     k->kp_state=0;
  284.     k->kp_offset=0;
  285.     k->kp_transpose=0;
  286. }
  287.  
  288. /*
  289.  * kiss_note_offline - tell kiss that the port went offline
  290.  */
  291. void kiss_note_offline(sfk_prt_pt p)
  292. {
  293.     kiss_clear_port(&p->K_IN);
  294.     kiss_clear_port(&p->K_OUT);
  295. }
  296.  
  297. /*
  298.  * read from packet queue
  299.  */
  300. static short kiss_in(CntrlParam *pb,DCtlPtr de,short op,void *extra)
  301. {
  302.     short csCode=pb->csCode;
  303.     register IOParam *ipb= (IOParam *)pb;
  304.     sfk_prt_pt p=extra;
  305.     switch(op) {
  306.     case sh_OPEN:
  307.         if(sfk_open_me(de))
  308.             return ioErr;
  309.         break;
  310.     case sh_CLOSE:
  311.         sfk_close_me(de);
  312.         break;
  313.     case sh_STATUS:
  314.         if(csCode==2) { //SetGetBuf
  315.             long *iocnt= (long*)&pb->csParam;
  316.             *iocnt=kiss_bytes_available(p);
  317.         } else if(csCode==8) { //SetStatus
  318.             SerStaRec st;
  319.             memset(&st,0,sizeof(st));
  320.             st.rdPend= (kiss_bytes_available(p)>0);
  321.             memcpy(&pb->csParam,&st,5);    //6? instead of 5?
  322.         }
  323.         break;
  324.     case sh_PRIME:
  325.         p->K_IN.kp_pb=(IOParam *)pb;
  326.         return kiss_read(p,FALSE);
  327.     case sh_CONTROL:
  328.         if (csCode==1)
  329.             sfk_mark_read_done(p,-27);
  330.         else if (csCode==accRun)
  331.             kiss_read(p,TRUE);
  332.         break;
  333.     default:
  334.         // DBO_fprintf((&p->dbo,"kiss_in op=%d csCode=%d\n",op,pb->csCode));
  335.         break;
  336.     }
  337.     return 0;
  338. }
  339.  
  340. /*
  341.  * turn on kiss mode on the passed port
  342.  */
  343. static void kiss_on(sfk_iio_pt cmd,sfk_prt_pt p)
  344. {
  345.     if(!p->sfk_IVAR(online))
  346.         sfk_parse_fail(cmd,TEXT_NUM(26),0);
  347.     sfk_allocate_soft_tnc_memory(cmd,p);
  348.     p->K_OUT.kp_transpose=FALSE;
  349.     sfk_fake_serial_install(cmd,p,
  350.         &p->K_IN,(long)&kiss_in,
  351.         &p->K_OUT,(long)&kiss_out);
  352.     p->sfk_IVAR(kiss)=TRUE;
  353. }
  354.  
  355. /*
  356.  * turn off kiss mode on the passed port
  357.  */
  358. static void sfk_kiss_off(sfk_iio_pt cmd,sfk_prt_pt p)
  359. {
  360.     p->sfk_IVAR(kiss)=FALSE;
  361.     sfk_soft_tnc_install(cmd,p);
  362. }
  363.  
  364. /*
  365.  * change kiss mode to on or off
  366.  */
  367. void sfk_change_kiss(sfk_iio_pt cmd,int new_setting)
  368. {
  369.     if(cmd->pqx.p->sfk_IVAR(kiss)==new_setting)
  370.         return;
  371.     if(cmd->pqx.p->pnum>1)
  372.       sfk_parse_fail(cmd,TEXT_NUM(27),0);
  373.     if(new_setting)
  374.         kiss_on(cmd,cmd->pqx.p);
  375.     else
  376.         sfk_kiss_off(cmd,cmd->pqx.p);
  377. }
  378.